#pragma once

#include "iostream"
#include "vector"
#include "algorithm"
#include "semaphore.h"

using namespace std;
/*HJJ QQ479287006
 *5 个沉默寡言的哲学家围坐在圆桌前，每人面前一盘意面。叉子放在哲学家之间的桌面上。（5 个哲学家，5 根叉子）

所有的哲学家都只会在思考和进餐两种行为间交替。哲学家只有同时拿到左边和右边的叉子才能吃到面，而同一根叉子在同一时间只能被一个哲学家使用。每个哲学家吃完面后都需要把叉子放回桌面以供其他哲学家吃面。只要条件允许，哲学家可以拿起左边或者右边的叉子，但在没有同时拿到左右叉子时不能进食。

假设面的数量没有限制，哲学家也能随便吃，不需要考虑吃不吃得下。

设计一个进餐规则（并行算法）使得每个哲学家都不会挨饿；也就是说，在没有人知道别人什么时候想吃东西或思考的情况下，每个哲学家都可以在吃饭和思考之间一直交替下去。

来源：力扣（LeetCode）
链接：https://leetcode.cn/problems/the-dining-philosophers
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * */
sem_t semArr[5];

DiningPhilosophers() {
//我草 要开几个锁啊

    sem_init(&semArr[0], 0, 1);
    sem_init(&semArr[1], 0, 1);
    sem_init(&semArr[2], 0, 1);
    sem_init(&semArr[3], 0, 1);
    sem_init(&semArr[4], 0, 1);

}

// 一直用例过不去 是因为
/**
 *      putLeftFork();
        putRightFork();
        sem_post(&semArr[right]);
        sem_post(&semArr[left]);
        输出和释放锁的顺序不一样
 *
 *
 * */
void wantsToEat(int philosopher,
                function<void()> pickLeftFork,
                function<void()> pickRightFork,
                function<void()> eat,
                function<void()> putLeftFork,
                function<void()> putRightFork) {
    // 拿右边 +0 拿左边-1
    // 如果是双数 拿左边 单数拿右边
    if (philosopher % 2 == 0) {
        //双数 左边
        int left = philosopher;


        sem_wait(&semArr[left]);


        int right = (philosopher + 1) % 5;
        //尝试拿右边筷子 如果拿不到同时释放左边筷子
        sem_wait(&semArr[right]);
        pickLeftFork();
        pickRightFork();
        eat();

        putLeftFork();
        putRightFork();
        sem_post(&semArr[right]);
        sem_post(&semArr[left]);


    } else {
        //先拿右边
        int right = (philosopher + 1) % 5;
        //尝试拿右边筷子 如果拿不到同时释放左边筷子
        sem_wait(&semArr[right]);


        //先拿右边
        int left = philosopher;
        if (left < 0)
            left = 4;

        sem_wait(&semArr[left]);
        pickRightFork();
        pickLeftFork();
        eat();

        putRightFork();
        putLeftFork();
        sem_post(&semArr[right]);
        sem_post(&semArr[left]);


    }


}
